home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C12 / Binary.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  12.5 KB  |  463 lines

  1. //: C12:Binary.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Overloading binary operators
  7. #include "../require.h"
  8. #include <fstream>
  9. using namespace std;
  10.  
  11. ofstream out("binary.out");
  12.  
  13. class Integer { // Combine this with Unary.cpp
  14.   long i;
  15. public:
  16.   Integer(long ll = 0) : i(ll) {}
  17.   // Operators that create new, modified value:
  18.   friend const Integer
  19.     operator+(const Integer& left,
  20.               const Integer& right);
  21.   friend const Integer
  22.     operator-(const Integer& left,
  23.               const Integer& right);
  24.   friend const Integer
  25.     operator*(const Integer& left,
  26.               const Integer& right);
  27.   friend const Integer
  28.     operator/(const Integer& left,
  29.               const Integer& right);
  30.   friend const Integer
  31.     operator%(const Integer& left,
  32.               const Integer& right);
  33.   friend const Integer
  34.     operator^(const Integer& left,
  35.               const Integer& right);
  36.   friend const Integer
  37.     operator&(const Integer& left,
  38.               const Integer& right);
  39.   friend const Integer
  40.     operator|(const Integer& left,
  41.               const Integer& right);
  42.   friend const Integer
  43.     operator<<(const Integer& left,
  44.                const Integer& right);
  45.   friend const Integer
  46.     operator>>(const Integer& left,
  47.                const Integer& right);
  48.   // Assignments modify & return lvalue:
  49.   friend Integer&
  50.     operator+=(Integer& left,
  51.                const Integer& right);
  52.   friend Integer&
  53.     operator-=(Integer& left,
  54.                const Integer& right);
  55.   friend Integer&
  56.     operator*=(Integer& left,
  57.                const Integer& right);
  58.   friend Integer&
  59.     operator/=(Integer& left,
  60.                const Integer& right);
  61.   friend Integer&
  62.     operator%=(Integer& left,
  63.                const Integer& right);
  64.   friend Integer&
  65.     operator^=(Integer& left,
  66.                const Integer& right);
  67.   friend Integer&
  68.     operator&=(Integer& left,
  69.                const Integer& right);
  70.   friend Integer&
  71.     operator|=(Integer& left,
  72.                const Integer& right);
  73.   friend Integer&
  74.     operator>>=(Integer& left,
  75.                 const Integer& right);
  76.   friend Integer&
  77.     operator<<=(Integer& left,
  78.                 const Integer& right);
  79.   // Conditional operators return true/false:
  80.   friend int
  81.     operator==(const Integer& left,
  82.                const Integer& right);
  83.   friend int
  84.     operator!=(const Integer& left,
  85.                const Integer& right);
  86.   friend int
  87.     operator<(const Integer& left,
  88.               const Integer& right);
  89.   friend int
  90.     operator>(const Integer& left,
  91.               const Integer& right);
  92.   friend int
  93.     operator<=(const Integer& left,
  94.                const Integer& right);
  95.   friend int
  96.     operator>=(const Integer& left,
  97.                const Integer& right);
  98.   friend int
  99.     operator&&(const Integer& left,
  100.                const Integer& right);
  101.   friend int
  102.     operator||(const Integer& left,
  103.                const Integer& right);
  104.   // Write the contents to an ostream:
  105.   void print(ostream& os) const { os << i; }
  106. };
  107.  
  108. const Integer
  109.   operator+(const Integer& left,
  110.             const Integer& right) {
  111.   return Integer(left.i + right.i);
  112. }
  113. const Integer
  114.   operator-(const Integer& left,
  115.             const Integer& right) {
  116.   return Integer(left.i - right.i);
  117. }
  118. const Integer
  119.   operator*(const Integer& left,
  120.             const Integer& right) {
  121.   return Integer(left.i * right.i);
  122. }
  123. const Integer
  124.   operator/(const Integer& left,
  125.             const Integer& right) {
  126.   require(right.i != 0, "divide by zero");
  127.   return Integer(left.i / right.i);
  128. }
  129. const Integer
  130.   operator%(const Integer& left,
  131.             const Integer& right) {
  132.   require(right.i != 0, "modulo by zero");
  133.   return Integer(left.i % right.i);
  134. }
  135. const Integer
  136.   operator^(const Integer& left,
  137.             const Integer& right) {
  138.   return Integer(left.i ^ right.i);
  139. }
  140. const Integer
  141.   operator&(const Integer& left,
  142.             const Integer& right) {
  143.   return Integer(left.i & right.i);
  144. }
  145. const Integer
  146.   operator|(const Integer& left,
  147.             const Integer& right) {
  148.   return Integer(left.i | right.i);
  149. }
  150. const Integer
  151.   operator<<(const Integer& left,
  152.              const Integer& right) {
  153.   return Integer(left.i << right.i);
  154. }
  155. const Integer
  156.   operator>>(const Integer& left,
  157.              const Integer& right) {
  158.   return Integer(left.i >> right.i);
  159. }
  160. // Assignments modify & return lvalue:
  161. Integer& operator+=(Integer& left,
  162.                     const Integer& right) {
  163.    if(&left == &right) {/* self-assignment */}
  164.    left.i += right.i;
  165.    return left;
  166. }
  167. Integer& operator-=(Integer& left,
  168.                     const Integer& right) {
  169.    if(&left == &right) {/* self-assignment */}
  170.    left.i -= right.i;
  171.    return left;
  172. }
  173. Integer& operator*=(Integer& left,
  174.                     const Integer& right) {
  175.    if(&left == &right) {/* self-assignment */}
  176.    left.i *= right.i;
  177.    return left;
  178. }
  179. Integer& operator/=(Integer& left,
  180.                     const Integer& right) {
  181.    require(right.i != 0, "divide by zero");
  182.    if(&left == &right) {/* self-assignment */}
  183.    left.i /= right.i;
  184.    return left;
  185. }
  186. Integer& operator%=(Integer& left,
  187.                     const Integer& right) {
  188.    require(right.i != 0, "modulo by zero");
  189.    if(&left == &right) {/* self-assignment */}
  190.    left.i %= right.i;
  191.    return left;
  192. }
  193. Integer& operator^=(Integer& left,
  194.                     const Integer& right) {
  195.    if(&left == &right) {/* self-assignment */}
  196.    left.i ^= right.i;
  197.    return left;
  198. }
  199. Integer& operator&=(Integer& left,
  200.                     const Integer& right) {
  201.    if(&left == &right) {/* self-assignment */}
  202.    left.i &= right.i;
  203.    return left;
  204. }
  205. Integer& operator|=(Integer& left,
  206.                     const Integer& right) {
  207.    if(&left == &right) {/* self-assignment */}
  208.    left.i |= right.i;
  209.    return left;
  210. }
  211. Integer& operator>>=(Integer& left,
  212.                      const Integer& right) {
  213.    if(&left == &right) {/* self-assignment */}
  214.    left.i >>= right.i;
  215.    return left;
  216. }
  217. Integer& operator<<=(Integer& left,
  218.                      const Integer& right) {
  219.    if(&left == &right) {/* self-assignment */}
  220.    left.i <<= right.i;
  221.    return left;
  222. }
  223. // Conditional operators return true/false:
  224. int operator==(const Integer& left,
  225.                const Integer& right) {
  226.     return left.i == right.i;
  227. }
  228. int operator!=(const Integer& left,
  229.                const Integer& right) {
  230.     return left.i != right.i;
  231. }
  232. int operator<(const Integer& left,
  233.               const Integer& right) {
  234.     return left.i < right.i;
  235. }
  236. int operator>(const Integer& left,
  237.               const Integer& right) {
  238.     return left.i > right.i;
  239. }
  240. int operator<=(const Integer& left,
  241.                const Integer& right) {
  242.     return left.i <= right.i;
  243. }
  244. int operator>=(const Integer& left,
  245.                const Integer& right) {
  246.     return left.i >= right.i;
  247. }
  248. int operator&&(const Integer& left,
  249.                const Integer& right) {
  250.     return left.i && right.i;
  251. }
  252. int operator||(const Integer& left,
  253.                const Integer& right) {
  254.     return left.i || right.i;
  255. }
  256.  
  257. void h(Integer& c1, Integer& c2) {
  258.   // A complex expression:
  259.   c1 += c1 * c2 + c2 % c1;
  260.   #define TRY(OP) \
  261.   out << "c1 = "; c1.print(out); \
  262.   out << ", c2 = "; c2.print(out); \
  263.   out << ";  c1 " #OP " c2 produces "; \
  264.   (c1 OP c2).print(out); \
  265.   out << endl;
  266.   TRY(+) TRY(-) TRY(*) TRY(/)
  267.   TRY(%) TRY(^) TRY(&) TRY(|)
  268.   TRY(<<) TRY(>>) TRY(+=) TRY(-=)
  269.   TRY(*=) TRY(/=) TRY(%=) TRY(^=)
  270.   TRY(&=) TRY(|=) TRY(>>=) TRY(<<=)
  271.   // Conditionals:
  272.   #define TRYC(OP) \
  273.   out << "c1 = "; c1.print(out); \
  274.   out << ", c2 = "; c2.print(out); \
  275.   out << ";  c1 " #OP " c2 produces "; \
  276.   out << (c1 OP c2); \
  277.   out << endl;
  278.   TRYC(<) TRYC(>) TRYC(==) TRYC(!=) TRYC(<=)
  279.   TRYC(>=) TRYC(&&) TRYC(||)
  280. }
  281.  
  282. // Member operators (implicit "this"):
  283. class Byte { // Combine this with Unary.cpp
  284.   unsigned char b;
  285. public:
  286.   Byte(unsigned char bb = 0) : b(bb) {}
  287.   // No side effects: const member function:
  288.   const Byte
  289.     operator+(const Byte& right) const {
  290.     return Byte(b + right.b);
  291.   }
  292.   const Byte
  293.     operator-(const Byte& right) const {
  294.     return Byte(b - right.b);
  295.   }
  296.   const Byte
  297.     operator*(const Byte& right) const {
  298.     return Byte(b * right.b);
  299.   }
  300.   const Byte
  301.     operator/(const Byte& right) const {
  302.     require(right.b != 0, "divide by zero");
  303.     return Byte(b / right.b);
  304.   }
  305.   const Byte
  306.     operator%(const Byte& right) const {
  307.     require(right.b != 0, "modulo by zero");
  308.     return Byte(b % right.b);
  309.   }
  310.   const Byte
  311.     operator^(const Byte& right) const {
  312.     return Byte(b ^ right.b);
  313.   }
  314.   const Byte
  315.     operator&(const Byte& right) const {
  316.     return Byte(b & right.b);
  317.   }
  318.   const Byte
  319.     operator|(const Byte& right) const {
  320.     return Byte(b | right.b);
  321.   }
  322.   const Byte
  323.     operator<<(const Byte& right) const {
  324.     return Byte(b << right.b);
  325.   }
  326.   const Byte
  327.     operator>>(const Byte& right) const {
  328.     return Byte(b >> right.b);
  329.   }
  330.   // Assignments modify & return lvalue.
  331.   // operator= can only be a member function:
  332.   Byte& operator=(const Byte& right) {
  333.     // Handle self-assignment:
  334.     if(this == &right) return *this;
  335.     b = right.b;
  336.     return *this;
  337.   }
  338.   Byte& operator+=(const Byte& right) {
  339.     if(this == &right) {/* self-assignment */}
  340.     b += right.b;
  341.     return *this;
  342.   }
  343.   Byte& operator-=(const Byte& right) {
  344.     if(this == &right) {/* self-assignment */}
  345.     b -= right.b;
  346.     return *this;
  347.   }
  348.   Byte& operator*=(const Byte& right) {
  349.     if(this == &right) {/* self-assignment */}
  350.     b *= right.b;
  351.     return *this;
  352.   }
  353.   Byte& operator/=(const Byte& right) {
  354.     require(right.b != 0, "divide by zero");
  355.     if(this == &right) {/* self-assignment */}
  356.     b /= right.b;
  357.     return *this;
  358.   }
  359.   Byte& operator%=(const Byte& right) {
  360.     require(right.b != 0, "modulo by zero");
  361.     if(this == &right) {/* self-assignment */}
  362.     b %= right.b;
  363.     return *this;
  364.   }
  365.   Byte& operator^=(const Byte& right) {
  366.     if(this == &right) {/* self-assignment */}
  367.     b ^= right.b;
  368.     return *this;
  369.   }
  370.   Byte& operator&=(const Byte& right) {
  371.     if(this == &right) {/* self-assignment */}
  372.     b &= right.b;
  373.     return *this;
  374.   }
  375.   Byte& operator|=(const Byte& right) {
  376.     if(this == &right) {/* self-assignment */}
  377.     b |= right.b;
  378.     return *this;
  379.   }
  380.   Byte& operator>>=(const Byte& right) {
  381.     if(this == &right) {/* self-assignment */}
  382.     b >>= right.b;
  383.     return *this;
  384.   }
  385.   Byte& operator<<=(const Byte& right) {
  386.     if(this == &right) {/* self-assignment */}
  387.     b <<= right.b;
  388.     return *this;
  389.   }
  390.   // Conditional operators return true/false:
  391.   int operator==(const Byte& right) const {
  392.       return b == right.b;
  393.   }
  394.   int operator!=(const Byte& right) const {
  395.       return b != right.b;
  396.   }
  397.   int operator<(const Byte& right) const {
  398.       return b < right.b;
  399.   }
  400.   int operator>(const Byte& right) const {
  401.       return b > right.b;
  402.   }
  403.   int operator<=(const Byte& right) const {
  404.       return b <= right.b;
  405.   }
  406.   int operator>=(const Byte& right) const {
  407.       return b >= right.b;
  408.   }
  409.   int operator&&(const Byte& right) const {
  410.       return b && right.b;
  411.   }
  412.   int operator||(const Byte& right) const {
  413.       return b || right.b;
  414.   }
  415.   // Write the contents to an ostream:
  416.   void print(ostream& os) const {
  417.     os << "0x" << hex << int(b) << dec;
  418.   }
  419. };
  420.  
  421. void k(Byte& b1, Byte& b2) {
  422.   b1 = b1 * b2 + b2 % b1;
  423.  
  424.   #define TRY2(OP) \
  425.   out << "b1 = "; b1.print(out); \
  426.   out << ", b2 = "; b2.print(out); \
  427.   out << ";  b1 " #OP " b2 produces "; \
  428.   (b1 OP b2).print(out); \
  429.   out << endl;
  430.  
  431.   b1 = 9; b2 = 47;
  432.   TRY2(+) TRY2(-) TRY2(*) TRY2(/)
  433.   TRY2(%) TRY2(^) TRY2(&) TRY2(|)
  434.   TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=)
  435.   TRY2(*=) TRY2(/=) TRY2(%=) TRY2(^=)
  436.   TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=)
  437.   TRY2(=) // Assignment operator
  438.  
  439.   // Conditionals:
  440.   #define TRYC2(OP) \
  441.   out << "b1 = "; b1.print(out); \
  442.   out << ", b2 = "; b2.print(out); \
  443.   out << ";  b1 " #OP " b2 produces "; \
  444.   out << (b1 OP b2); \
  445.   out << endl;
  446.  
  447.   b1 = 9; b2 = 47;
  448.   TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=)
  449.   TRYC2(>=) TRYC2(&&) TRYC2(||)
  450.  
  451.   // Chained assignment:
  452.   Byte b3 = 92;
  453.   b1 = b2 = b3;
  454. }
  455.  
  456. int main() {
  457.   Integer c1(47), c2(9);
  458.   h(c1, c2);
  459.   out << "\n member functions:" << endl;
  460.   Byte b1(47), b2(9);
  461.   k(b1, b2);
  462. } ///:~
  463.